package gmodel

import (
	"database/sql/driver"
	"fmt"
	"github.com/andeya/ameda"
	"math"
	"strconv"
)

/*
Precision4

	4位小数类型，实现gorm的自定义数据类型，保存时精度限制为4位小数，用于金额（精确到毫），百分比等场景
	gorm声明支持：

		gorm:"type:decimal(11,4)
		"gorm:"precision:11,4"
*/
type Precision4 float64

// 实现 JSON 序列化接口
func (d Precision4) MarshalJSON() ([]byte, error) {
	return []byte(fmt.Sprintf("%.4f", d)), nil
}

// 实现 SQL 的扫描接口
func (d *Precision4) Scan(value interface{}) (err error) {
	floatV := float64(0)
	switch v := value.(type) {
	case float64: // 数据库返回的 float64
		floatV = v
	case []byte: // 数据库返回的十进制字符串
		floatV, err = strconv.ParseFloat(string(v), 64)
		if err != nil {
			return fmt.Errorf("invalid type for Amount: %v", err)
		}
	case string: // 数据库返回字符串
		floatV, err = strconv.ParseFloat(v, 64)
		if err != nil {
			return fmt.Errorf("invalid type for Amount: %v", err)
		}
	default: // 不支持的类型
		return fmt.Errorf("invalid type for Amount: %T", value)
	}
	*d = Precision4(math.Round(floatV*10000) / 10000)
	return nil
}

// 实现 SQL 的值接口
func (d Precision4) Value() (driver.Value, error) {
	return d.Float64(), nil
}

// 转float64保留2位小数,四舍五入,比较运算时用这个方法转成float64比较,避免浮点值问题
func (d Precision4) Float64() float64 {
	return math.Round(float64(d)*10000) / 10000
}

func StringToPrecision4(v string) (p Precision4, err error) {
	fv, err := ameda.StringToFloat64(v)
	if err != nil {
		return 0, err
	}
	return Precision4(fv), nil
}

//// 金额转成分
//func Precision2ToIntX100[T int | int64](d Precision2) (T, error) {
//	var zero T // 泛型零值
//	floatValue := d.Float64() * 100
//
//	// 根据目标类型进行转换
//	switch any(zero).(type) {
//	case int:
//		intValue, err := strconv.Atoi(fmt.Sprintf("%.0f", floatValue))
//		if err != nil {
//			return zero, fmt.Errorf("failed to convert to int: %v", err)
//		}
//		return T(intValue), nil
//	case int64:
//		intValue, err := strconv.ParseInt(fmt.Sprintf("%.0f", floatValue), 10, 64)
//		if err != nil {
//			return zero, fmt.Errorf("failed to convert to int64: %v", err)
//		}
//		return T(intValue), nil
//	default:
//		return zero, fmt.Errorf("unsupported type: %T", zero)
//	}
//}
//
//// 泛型函数：将 Precision2 转换为指定类型的整数值（单位：分），出错时 panic
//func Precision2ToIntX100Must[T int | int64](d Precision2) T {
//	value, err := Precision2ToIntX100[T](d)
//	if err != nil {
//		panic(err)
//	}
//	return value
//}
